package cn.lh.user.service.impl;

import cn.lh.basic.constants.VerifyCodeConstants;
import cn.lh.basic.jwt.JwtUtils;
import cn.lh.basic.jwt.RsaUtils;
import cn.lh.basic.service.impl.BaseServiceImpl;
import cn.lh.basic.util.HttpUtil;
import cn.lh.basic.util.JsonResult;
import cn.lh.basic.util.Md5Utils;
import cn.lh.basic.util.StrUtils;
import cn.lh.org.domain.Employee;
import cn.lh.org.exception.BusinessException;
import cn.lh.org.mapper.EmployeeMapper;
import cn.lh.system.domain.Menu;
import cn.lh.system.domain.Permission;
import cn.lh.user.constant.WxConstants;
import cn.lh.user.domain.Logininfo;
import cn.lh.user.domain.User;
import cn.lh.user.domain.Wxuser;
import cn.lh.user.dto.BinderDto;
import cn.lh.user.dto.LoginDto;
import cn.lh.user.mapper.LogininfoMapper;
import cn.lh.user.mapper.UserMapper;
import cn.lh.user.mapper.WxuserMapper;
import cn.lh.user.service.ILogininfoService;
import cn.lh.user.util.LoginData;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.security.PrivateKey;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * 业务实现类：
 */
@Service
public class LogininfoServiceImpl extends BaseServiceImpl<Logininfo> implements ILogininfoService {

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private EmployeeMapper employeeMapper;

    @Autowired
    private WxuserMapper wxuserMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public Map<String, Object> accountLogin(LoginDto loginDto) {
        String Account = loginDto.getAccount();
        String password = loginDto.getPassword();
        Integer type = loginDto.getType();
        // 非公校验
        Map<String, Object> map = new HashMap<>();
        if (StringUtils.isEmpty(Account)
                || StringUtils.isEmpty(password)
                || StringUtils.isEmpty(type)) {
            throw new BusinessException("参数不能为空");
        }
        Logininfo logininfo = logininfoMapper.findByAccount(loginDto);
        if (logininfo == null) {
            throw new BusinessException("用户名或密码错误");
        }
        // 盐值+密码进行校验
        String salt = logininfo.getSalt();
        String md5Pwd = Md5Utils.encrypByMd5(salt + password);
        if (!md5Pwd.equals(logininfo.getPassword())) {
            throw new BusinessException("用户名或密码错误");
        }
        //1.3.状态校验 - 启用，禁用
        if (!logininfo.getDisable()) {
            throw new BusinessException("你的账号被冻结，请联系管理员!!!");
        }
//        // uuid生成token令牌
//        String token = UUID.randomUUID().toString();
//        // 将token作为键，logininfo作为值存在redis中
//        redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);
//        // 为了安全密码和盐值不用返回给浏览器
//        logininfo.setPassword(null);
//        logininfo.setSalt(null);
//        // 将令牌和登录信息返回给浏览器
//        map.put("token", token);
//        map.put("logininfo", logininfo);
//        return map;
        return loginSuccessJwtHandler(logininfo);
    }

    @Override
    public JsonResult wechatLogin(String code) {
        Map<String, Object> map = new HashMap<>();
        String url = WxConstants.GET_ACK_URL
                .replace("APPID", WxConstants.APPID)
                .replace("SECRET", WxConstants.SECRET)
                .replace("CODE", code);
        String jsonStr = HttpUtil.httpGet(url);
        JSONObject jsonObj = JSONObject.parseObject(jsonStr);
        String access_token = jsonObj.getString("access_token");
        String openid = jsonObj.getString("openid");
        Wxuser wxuser = wxuserMapper.loadByOpenid(openid);
        if (wxuser != null && wxuser.getUserId() != null) {
            Logininfo logininfo = logininfoMapper.loadLogininfoByUserId(wxuser.getUserId());
//            String token = UUID.randomUUID().toString();
//            redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);
//            map.put("token", token);
//            map.put("logininfo", logininfo);
            map = loginSuccessJwtHandler(logininfo);
            JsonResult.set(true, "登录成功");
            return JsonResult.setResultObject(map);
        } else {
            map.put("access_token", access_token);
            map.put("openid", openid);
            JsonResult.set(false, "微信未邦定用户");
            JsonResult.setResultObject(map);
            return JsonResult.setResultObject(map);
        }
    }

    @Override
    public JsonResult wechatBinder(BinderDto binderDto) {
        String phone = binderDto.getPhone();
        String verifyCode = binderDto.getVerifyCode();
        String accessToken = binderDto.getAccessToken();
        String openId = binderDto.getOpenId();
        //校验
        //1.校验 空值校验
        if (StringUtils.isEmpty(phone)
                || StringUtils.isEmpty(verifyCode)
                || StringUtils.isEmpty(accessToken)
                || StringUtils.isEmpty(openId)
        ) {
            throw new BusinessException("参数不能为空");
        }
        System.out.println(VerifyCodeConstants.BINDER_PREFIX + phone);
        Object valueObj = redisTemplate.opsForValue().get(VerifyCodeConstants.BINDER_PREFIX + phone);
        if (valueObj == null) {
            throw new BusinessException("短信验证码过期");
        }
        String redisSmsCode = valueObj.toString().split(":")[1];
        if (!verifyCode.equals(redisSmsCode)) {
            throw new BusinessException("短信验证码不正确");
        }
        String url = WxConstants.GET_USER_URL
                .replace("ACCESS_TOKEN", accessToken)
                .replace("OPENID", openId);
        String jsonStr = HttpUtil.httpGet(url);
        Wxuser wxuser = jsonStr2Wxuser(jsonStr);
        User user = userMapper.findByPhone(phone);
        if (user == null) {
            user = phone2User(phone);
            Logininfo logininfoTmp = user2Logininfo(user);
            logininfoMapper.save(logininfoTmp);
            user.setLogininfoId(logininfoTmp.getId());
            userMapper.save(user);
        }
        wxuser.setUserId(user.getId());
        wxuserMapper.save(wxuser);
        Logininfo logininfo = logininfoMapper.loadById(user.getLogininfoId());
//        String token = UUID.randomUUID().toString();
//        redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);
//        Map map = new HashMap<String, Object>();
//        map.put("token", token);
//        map.put("logininfo", logininfo);
        Map<String, Object> map = loginSuccessJwtHandler(logininfo);
        JsonResult.set(true, "登录成功");
        return JsonResult.setResultObject(map);
    }

    @Override
    public JsonResult logout(String token) {
        if (token == null) {
            throw new BusinessException("参数为空");
        }
        redisTemplate.delete(token);
        return JsonResult.set(true, "退出登录成功");
    }

    public Map<String, Object> loginSuccessJwtHandler(Logininfo logininfo) {
        try {
            Map<String, Object> map = new HashMap<>();
            LoginData loginData = new LoginData();
            loginData.setLogininfo(logininfo);
            if (logininfo.getType() == 0) {
                List<String> permissions = employeeMapper.loadPermissionsByLogininfoId(logininfo.getId());
                List<Menu> menus = employeeMapper.loadMenusByLogininfoId(logininfo.getId());
                loginData.setPermissions(permissions);
                loginData.setMenus(menus);
                map.put("permissions", permissions);
                map.put("menus", menus);
            }
            PrivateKey privateKey = RsaUtils.getPrivateKey(RsaUtils.class.getClassLoader().getResource("auth_rsa.pri").getFile());
            //将登陆人信息加密得到jwtToken串
            String jwtToken = JwtUtils.generateTokenExpireInMinutes(loginData, privateKey, 720);
            map.put("token", jwtToken);
            map.put("logininfo", logininfo);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private Logininfo user2Logininfo(User user) {
        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user, logininfo);
        logininfo.setType(1);
        return logininfo;
    }

    private User phone2User(String phone) {
        User user = new User();
        user.setUsername(phone);
        user.setPhone(phone);
        String salt = StrUtils.getComplexRandomString(32);
        //随机的纯数据密码
        String randomPwd = StrUtils.getRandomString(6);
        String md5Pwd = Md5Utils.encrypByMd5(randomPwd + salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);
        return user;
    }

    private Wxuser jsonStr2Wxuser(String jsonStr) {
        Wxuser wxuser = new Wxuser();
        JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        wxuser.setOpenid(jsonObject.getString("openid"));
        wxuser.setNickname(jsonObject.getString("nickname"));
        wxuser.setSex(jsonObject.getInteger("sex"));
        wxuser.setAddress(jsonObject.getString("country") + jsonObject.getString("province") + jsonObject.getString("city"));
        wxuser.setHeadimgurl(jsonObject.getString("headimgurl"));
        wxuser.setUnionid(jsonObject.getString("unionid"));
        return wxuser;
    }
}
